﻿
namespace Patterns4Net.Attributes
{
    using System;
    using Relations;

    /// <summary>
    /// <para>
    /// Don't use this attribute if you don't know what you are doing!
    /// This attribute is intended for patterns authors, not for users. 
    /// Concrete roles of a pattern should by marked by the pattern specific attributes.
    /// </para>
    /// <para>
    /// Value(s) of property annotated with this attribute is (are) considered as pattern roles.
    /// Use this attribute to annotate properties of classes derived from <see cref="IPattern"/>. 
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>
    /// This attribute is valid only on properties of types derived from <see cref="IPattern"/> 
    /// and only on properties of following types: 
    /// <list type="table">
    ///     <item><term><see cref="System.Type"/></term></item>
    ///     <item><term>Mono.Cecil.TypeReference</term></item>
    ///     <item><term>Mono.Cecil.TypeDefinition</term></item>
    ///     <item><term>Mono.Cecil.MethodReference</term></item>
    ///     <item><term>Mono.Cecil.MethodDefinition</term></item>
    ///     <item><term>and IEnumerable{T} where T is one of the above.</term></item>
    /// </list>
    /// </para>
    /// </remarks>
    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class PatternRoleAttribute : Attribute
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PatternRoleAttribute"/> class.
        /// </summary>
        public PatternRoleAttribute()
        {
            this.RelationType = RelationType.None;
            this.Cardinality = Cardinality.One;
        }

        /// <summary>
        /// Gets or sets the name of the role.
        /// If left <c>null</c> or empty, the name of annotated property 
        /// will be used instead.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the type of the relationship (e. g. composition).
        /// If left blank, the relation is inferred automatically 
        /// (however inferred relation type may not be correct).
        /// </summary>
        public RelationType RelationType { get; set; }

        /// <summary>
        /// Gets or sets the cardinality of the relation.
        /// Default value is set to <see cref="Patterns4Net.Attributes.Relations.Cardinality.One"/>.
        /// </summary>
        public Cardinality Cardinality { get; set; }
    }

    public enum RelationType
    {
        Composition,
        Aggregation,
        Association,
        Inheritance,
        Uses,
        None
    };
}
